package pe.gob.minam.sismon.core.base.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.transaction.annotation.Transactional;

import pe.gob.minam.sismon.core.base.dao.BaseDao;
import pe.gob.minam.sismon.core.util.ExceptionCore;

public class BaseDaoImpl<E> implements BaseDao<E> {

	@PersistenceContext
	private EntityManager entityManager;
	private Class<E> entityClass;

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager)
			throws ExceptionCore {
		this.entityManager = entityManager;
	}

	@Transactional
	public E insertar(E e) throws ExceptionCore {
		getEntityManager().persist(e);
		return e;
	}

	@Transactional
	public E actualizar(E e) throws ExceptionCore {
		getEntityManager().merge(e);
		return e;
	}

	@Transactional
	public Integer eliminar(Object id) throws ExceptionCore {
		getEntityManager().remove(
				(E) getEntityManager().find(getEntityClass(), id));
		return 1;

	}

	public E obtener(Object id) throws ExceptionCore {
		return (E) getEntityManager().find(getEntityClass(), id);
	}

	@SuppressWarnings("unchecked")
	public List<E> listar() throws ExceptionCore {
		return getEntityManager()
				.createQuery(
						new StringBuilder().append("from ")
								.append(getEntityClass().getCanonicalName())
								.toString()).getResultList();
	}

	@SuppressWarnings("unchecked")
	public Class<E> getEntityClass() throws ExceptionCore {
		if (entityClass == null) {
			Type type = getClass().getGenericSuperclass();
			if (type instanceof ParameterizedType) {
				ParameterizedType paramType = (ParameterizedType) type;
				if (paramType.getActualTypeArguments().length == 2) {
					if (paramType.getActualTypeArguments()[1] instanceof TypeVariable) {
						throw new IllegalArgumentException(
								"Could not guess entity class by reflection");
					} else {
						entityClass = (Class<E>) paramType
								.getActualTypeArguments()[1];
					}
				} else {
					entityClass = (Class<E>) paramType.getActualTypeArguments()[0];
				}
			}
		}
		return entityClass;
	}
}
